package com.hbpu.maven.spring.aop.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * 环绕通知切面类，用于拦截 MathCalculator 接口的所有方法，并在方法执行前后、返回值处理及异常处理阶段插入自定义逻辑。
 * 使用 AOP 技术实现对目标方法的全方位控制，包括前置操作、后置操作、返回值日志记录以及异常捕获。
 */
@Order(99)
@Aspect
@Component
public class AroundAspect {
    /**
     * 定义切点表达式，匹配 MathCalculator 接口中所有返回值为 int 类型的方法。
     * 切点表达式的范围限定为 com.hbpu.maven.spring.aop.calculator.MathCalculator 包下的所有方法。
     */
    @Pointcut("execution(int com.hbpu.maven.spring.aop.calculator.MathCalculator.*(..))")
    public void pointcut() {
    }

    /**
     * 环绕通知方法，在匹配的方法执行前后插入自定义逻辑。
     * 具体逻辑包括：打印方法参数、执行目标方法、捕获并处理异常、打印返回值以及执行后置操作。
     *
     * @param joinPoint 连接点对象，包含目标方法的详细信息（如方法名、参数列表等）。
     * @return 目标方法的返回值。
     * @throws Throwable 如果目标方法抛出异常，则将异常向上抛出。
     */
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] args = joinPoint.getArgs();
        System.out.println("around-前置，参数为：" + Arrays.toString(args));

        try {
            Object proceed = joinPoint.proceed(args);
            System.out.println("around-返回，返回值为：" + proceed);
            return proceed;
        } catch (Exception e) {
            System.out.println("around-异常" + e.getMessage());
            throw e;
        } finally {
            System.out.println("around-后置");
        }
    }
}
